package com.yiyi.user.config;


import cn.hutool.json.JSONUtil;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PrivateKey;
import java.util.ArrayList;

@Configuration
public class WeiXinConfig {

    @Autowired
    private Config wxPayConfig; // 注入 WxPayConfig 中的 Config 实例

    /** 商户号 */
    @Value("${wxpay.mchId}")
    public  String merchantId;
    /** 商户API私钥路径 */
    @Value("${wxpay.keyPath}")
    public  String privateKeyPath;
    /** 商户证书序列号 */
    @Value("${wxpay.mcSerialNo}")
    public  String merchantSerialNumber;
    /** 商户APIV3密钥 */
    @Value("${wxpay.apiV3Key}")
    public  String apiV3Key;
    @Value("${wxpay.appId}")
    public  String appId;
    @Value("${wxpay.jsApiNotifyDomain}")
    public  String jsApiNotifyDomain;
    @Value("${wxpay.notifyDomain}")
    public  String notifyDomain;

    @Bean
    public JsapiService jsapiService() {
        JsapiService service = new JsapiService.Builder().config(wxPayConfig).build();
        return service;
    }

    /**
     * 签名
     * @param message
     * @return
     * @throws IOException
     */
    public String signV3(byte[] message) throws IOException {
        // 构建 - 签名工具类
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(merchantSerialNumber,
                getPrivateKey(privateKeyPath));
        return privateKeySigner.sign(message).getSign();
    }

    /**
     * 获取私钥。
     * 这是个静态方法，可以直接用类名调用
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     * <p>
     * 完全不需要修改，注意此方法也是去掉了头部和尾部，注意文件路径名
     */
    public static PrivateKey getPrivateKey(String filename) throws IOException {
        String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
        return PemUtil.loadPrivateKey(content);
    }

    /**
     * 转换 - 加密数据
     **/
    public static String buildSignMessage(ArrayList<String> signMessage) {
        if (signMessage == null || signMessage.size() <= 0) {
            return null;
        }
        StringBuilder sbf = new StringBuilder();
        for (String str : signMessage) {
            sbf.append(str).append("\n");
        }
        return sbf.toString();
    }

    /**
     * 获取 - 微信支付回调通知请求头body内容
     **/
    public String getVerifyNotifyBody(HttpServletRequest request) {
        BufferedReader br = null;
        try {
            StringBuilder result = new StringBuilder();
            br = request.getReader();
            for (String line; (line = br.readLine()) != null; ) {
                if (result.length() > 0) {
                    result.append("\n");
                }
                result.append(line);
            }
            return result.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * v3 支付异步通知验证签名
     *
     * @param body 异步通知密文
     * @param key  api 密钥
     * @return 异步通知明文
     * @throws Exception 异常信息
     */
    public String verifyNotify(String body, String key) throws Exception {
        // 获取 - 请求body相关加密信息
        cn.hutool.json.JSONObject resultObject = JSONUtil.parseObj(body);
        cn.hutool.json.JSONObject resource = resultObject.getJSONObject("resource");
        String cipherText = resource.getStr("ciphertext");
        String nonceStr = resource.getStr("nonce");
        String associatedData = resource.getStr("associated_data");

        // 构造 - 解密工具类
        AesUtil aesUtil = new AesUtil(key.getBytes(StandardCharsets.UTF_8));

        // 操作 - 密文解密
        String result = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonceStr.getBytes(StandardCharsets.UTF_8), cipherText);
        System.out.print("微信支付成功，解密回调信息 - result : {}");
        System.out.println(result);
        return result;
    }

}
